feat: support global paths for Codex command generation#622
Conversation
Codex custom prompts live in ~/.codex/prompts/ (global, not per-project). Update the Codex adapter to return absolute paths via os.homedir(), handle absolute paths in init/update writers, and update docs and specs to reflect the change.
📝 WalkthroughWalkthroughUpdates Codex prompt handling to use a global home directory ( Changes
Sequence Diagram(s)sequenceDiagram
participant CLI
participant Init/Update
participant CodexAdapter
participant FS
participant Env as Environment
CLI->>Init/Update: generate/update commands (cmd.path)
Init/Update->>CodexAdapter: ToolCommandAdapter.getFilePath(commandId)
CodexAdapter->>Env: read CODEX_HOME
Env-->>CodexAdapter: CODEX_HOME or undefined
CodexAdapter->>CodexAdapter: getCodexHome() -> resolve path (CODEX_HOME or os.homedir()+/.codex)
CodexAdapter-->>Init/Update: return absolute file path for Codex command
Init/Update->>Init/Update: if path is absolute use as-is else join with project path
Init/Update->>FS: write command file to resolved path
FS-->>Init/Update: write result
Init/Update-->>CLI: completion
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Review CompleteYour review story is ready! Comment !reviewfast on this PR to re-generate the story. |
Greptile OverviewGreptile SummaryThis PR adds support for global path installation in the Codex adapter, allowing commands to be installed to Key changes:
The implementation is clean, well-tested, and backwards-compatible. The Confidence Score: 5/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant InitCommand
participant UpdateCommand
participant CommandAdapterRegistry
participant CodexAdapter
participant FileSystemUtils
participant OS
User->>InitCommand: opsx init --tools codex
InitCommand->>CommandAdapterRegistry: get('codex')
CommandAdapterRegistry-->>InitCommand: codexAdapter
InitCommand->>CodexAdapter: getFilePath('explore')
CodexAdapter->>OS: process.env.CODEX_HOME?
alt CODEX_HOME set
OS-->>CodexAdapter: /custom/codex-home
CodexAdapter->>CodexAdapter: path.resolve(CODEX_HOME)
else CODEX_HOME not set
CodexAdapter->>OS: os.homedir()
OS-->>CodexAdapter: /home/user
CodexAdapter->>CodexAdapter: path.join(homedir, '.codex')
end
CodexAdapter-->>InitCommand: /home/user/.codex/prompts/opsx-explore.md
InitCommand->>InitCommand: path.isAbsolute(cmd.path)?
alt path is absolute
InitCommand->>FileSystemUtils: writeFile(absolutePath, content)
else path is relative
InitCommand->>FileSystemUtils: writeFile(projectPath + relativePath, content)
end
FileSystemUtils->>FileSystemUtils: createDirectory(dirname)
FileSystemUtils->>OS: fs.writeFile()
FileSystemUtils-->>InitCommand: Success
InitCommand-->>User: Codex commands installed to ~/.codex/prompts/
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@src/core/command-generation/adapters/codex.ts`:
- Around line 14-20: getCodexHome currently treats an empty CODEX_HOME env var
as set and resolves to CWD; change getCodexHome to treat empty/whitespace-only
CODEX_HOME as unset by trimming and checking length (e.g. const homeEnv =
process.env.CODEX_HOME?.trim(); if (!homeEnv) use path.join(os.homedir(),
'.codex') ), then pass the chosen path to path.resolve so an empty value no
longer causes writes into the project directory; update the getCodexHome
function accordingly.
In `@test/core/command-generation/adapters.test.ts`:
- Around line 214-217: The test for codexAdapter.getFilePath('explore') is
brittle because it asserts the prefix ".codex" which fails when CODEX_HOME is
customized; change the assertion to only verify the suffix structure by either
checking filePath.endsWith(path.join('prompts', 'opsx-explore.md')) or using a
looser regex like /[\\/ ]?prompts[\\/]opsx-explore\.md$/ (or simply
/[\\/]prompts[\\/]opsx-explore\.md$/) so the test still validates the final path
segment without depending on a specific CODEX_HOME prefix; update the test case
in the 'should generate path ending with correct structure' spec that calls
codexAdapter.getFilePath('explore').
🧹 Nitpick comments (1)
openspec/changes/multi-provider-skill-generation/design.md (1)
20-45: Clarify the “non-goal but implemented” phrasing.
Consider rewording to indicate global paths are out of scope except Codex, to avoid contradictory wording.✏️ Suggested wording
-- Global path installation — implemented for Codex (absolute path from adapter) +- Global path installation for tools other than Codex (Codex uses absolute adapter paths today)
- Guard against empty CODEX_HOME resolving to CWD by trimming the env var - Loosen test regex to not depend on .codex prefix (resilient to custom CODEX_HOME) - Clarify non-goal wording in design.md to avoid contradictory phrasing
Summary
~/.codex/prompts/) viaos.homedir(), respectingCODEX_HOMEenv varinit.tsandupdate.tsfile writers withpath.isAbsolute()guardsupported-tools.md), spec (spec.md), and design (design.md) to reflect global-path support and fix stale "deferred" rationaleCODEX_HOMEoverrideTest plan
npm run buildpasses with no type errorsnpm test— all 1236 tests pass, including new Codex adapter tests for absolute paths andCODEX_HOMEsupported-tools.mdfootnote renders correctly on GitHub🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Documentation
Tests
✏️ Tip: You can customize this high-level summary in your review settings.